home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tk8.0 / generic / tkBitmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  16.9 KB  |  586 lines  |  [TEXT/CWIE]

  1. /* 
  2.  * tkBitmap.c --
  3.  *
  4.  *    This file maintains a database of read-only bitmaps for the Tk
  5.  *    toolkit.  This allows bitmaps to be shared between widgets and
  6.  *    also avoids interactions with the X server.
  7.  *
  8.  * Copyright (c) 1990-1994 The Regents of the University of California.
  9.  * Copyright (c) 1994-1996 Sun Microsystems, Inc.
  10.  *
  11.  * See the file "license.terms" for information on usage and redistribution
  12.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  13.  *
  14.  * SCCS: @(#) tkBitmap.c 1.45 97/07/24 17:27:38
  15.  */
  16.  
  17. #include "tkPort.h"
  18. #include "tkInt.h"
  19.  
  20. /*
  21.  * The includes below are for pre-defined bitmaps.
  22.  *
  23.  * Platform-specific issue: Windows complains when the bitmaps are
  24.  * included, because an array of characters is being initialized with
  25.  * integers as elements.  For lint purposes, the following pragmas
  26.  * temporarily turn off that warning message.
  27.  */
  28.  
  29. #if defined(__WIN32__) || defined(_WIN32)
  30. #pragma warning (disable : 4305)
  31. #endif
  32.  
  33. #include "error.bmp"
  34. #include "gray12.bmp"
  35. #include "gray25.bmp"
  36. #include "gray50.bmp"
  37. #include "gray75.bmp"
  38. #include "hourglass.bmp"
  39. #include "info.bmp"
  40. #include "questhead.bmp"
  41. #include "question.bmp"
  42. #include "warning.bmp"
  43.  
  44. #if defined(__WIN32__) || defined(_WIN32)
  45. #pragma warning (default : 4305)
  46. #endif
  47.  
  48. /*
  49.  * One of the following data structures exists for each bitmap that is
  50.  * currently in use.  Each structure is indexed with both "idTable" and
  51.  * "nameTable".
  52.  */
  53.  
  54. typedef struct {
  55.     Pixmap bitmap;        /* X identifier for bitmap.  None means this
  56.                  * bitmap was created by Tk_DefineBitmap
  57.                  * and it isn't currently in use. */
  58.     int width, height;        /* Dimensions of bitmap. */
  59.     Display *display;        /* Display for which bitmap is valid. */
  60.     int refCount;        /* Number of active uses of bitmap. */
  61.     Tcl_HashEntry *hashPtr;    /* Entry in nameTable for this structure
  62.                  * (needed when deleting). */
  63. } TkBitmap;
  64.  
  65. /*
  66.  * Hash table to map from a textual description of a bitmap to the
  67.  * TkBitmap record for the bitmap, and key structure used in that
  68.  * hash table:
  69.  */
  70.  
  71. static Tcl_HashTable nameTable;
  72. typedef struct {
  73.     Tk_Uid name;        /* Textual name for desired bitmap. */
  74.     Screen *screen;        /* Screen on which bitmap will be used. */
  75. } NameKey;
  76.  
  77. /*
  78.  * Hash table that maps from <display + bitmap id> to the TkBitmap structure
  79.  * for the bitmap.  This table is used by Tk_FreeBitmap.
  80.  */
  81.  
  82. static Tcl_HashTable idTable;
  83. typedef struct {
  84.     Display *display;        /* Display for which bitmap was allocated. */
  85.     Pixmap pixmap;        /* X identifier for pixmap. */
  86. } IdKey;
  87.  
  88. /*
  89.  * Hash table create by Tk_DefineBitmap to map from a name to a
  90.  * collection of in-core data about a bitmap.  The table is
  91.  * indexed by the address of the data for the bitmap, and the entries
  92.  * contain pointers to TkPredefBitmap structures.
  93.  */
  94.  
  95. Tcl_HashTable tkPredefBitmapTable;
  96.  
  97. /*
  98.  * Hash table used by Tk_GetBitmapFromData to map from a collection
  99.  * of in-core data about a bitmap to a Tk_Uid giving an automatically-
  100.  * generated name for the bitmap:
  101.  */
  102.  
  103. static Tcl_HashTable dataTable;
  104. typedef struct {
  105.     char *source;        /* Bitmap bits. */
  106.     int width, height;        /* Dimensions of bitmap. */
  107. } DataKey;
  108.  
  109. static int initialized = 0;    /* 0 means static structures haven't been
  110.                  * initialized yet. */
  111.  
  112. /*
  113.  * Forward declarations for procedures defined in this file:
  114.  */
  115.  
  116. static void        BitmapInit _ANSI_ARGS_((void));
  117.  
  118. /*
  119.  *----------------------------------------------------------------------
  120.  *
  121.  * Tk_GetBitmap --
  122.  *
  123.  *    Given a string describing a bitmap, locate (or create if necessary)
  124.  *    a bitmap that fits the description.
  125.  *
  126.  * Results:
  127.  *    The return value is the X identifer for the desired bitmap
  128.  *    (i.e. a Pixmap with a single plane), unless string couldn't be
  129.  *    parsed correctly.  In this case, None is returned and an error
  130.  *    message is left in interp->result.  The caller should never
  131.  *    modify the bitmap that is returned, and should eventually call
  132.  *    Tk_FreeBitmap when the bitmap is no longer needed.
  133.  *
  134.  * Side effects:
  135.  *    The bitmap is added to an internal database with a reference count.
  136.  *    For each call to this procedure, there should eventually be a call
  137.  *    to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
  138.  *    aren't needed anymore.
  139.  *
  140.  *----------------------------------------------------------------------
  141.  */
  142.  
  143. Pixmap
  144. Tk_GetBitmap(interp, tkwin, string)
  145.     Tcl_Interp *interp;        /* Interpreter to use for error reporting,
  146.                  * this may be NULL. */
  147.     Tk_Window tkwin;        /* Window in which bitmap will be used. */
  148.     Tk_Uid string;        /* Description of bitmap.  See manual entry
  149.                  * for details on legal syntax. */
  150. {
  151.     NameKey nameKey;
  152.     IdKey idKey;
  153.     Tcl_HashEntry *nameHashPtr, *idHashPtr, *predefHashPtr;
  154.     register TkBitmap *bitmapPtr;
  155.     TkPredefBitmap *predefPtr;
  156.     int new;
  157.     Pixmap bitmap;
  158.     int width, height;
  159.     int dummy2;
  160.  
  161.     if (!initialized) {
  162.     BitmapInit();
  163.     }
  164.  
  165.     nameKey.name = string;
  166.     nameKey.screen = Tk_Screen(tkwin);
  167.     nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &nameKey, &new);
  168.     if (!new) {
  169.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr);
  170.     bitmapPtr->refCount++;
  171.     return bitmapPtr->bitmap;
  172.     }
  173.  
  174.     /*
  175.      * No suitable bitmap exists.  Create a new bitmap from the
  176.      * information contained in the string.  If the string starts
  177.      * with "@" then the rest of the string is a file name containing
  178.      * the bitmap.  Otherwise the string must refer to a bitmap
  179.      * defined by a call to Tk_DefineBitmap.
  180.      */
  181.  
  182.     if (*string == '@') {
  183.     Tcl_DString buffer;
  184.     int result;
  185.  
  186.         if (Tcl_IsSafe(interp)) {
  187.             Tcl_AppendResult(interp, "can't specify bitmap with '@' in a",
  188.                     " safe interpreter", (char *) NULL);
  189.             goto error;
  190.         }
  191.         
  192.     string = Tcl_TranslateFileName(interp, string + 1, &buffer);
  193.     if (string == NULL) {
  194.         goto error;
  195.     }
  196.     result = XReadBitmapFile(Tk_Display(tkwin),
  197.         RootWindowOfScreen(nameKey.screen), string,
  198.         (unsigned int *) &width, (unsigned int *) &height,
  199.         &bitmap, &dummy2, &dummy2);
  200.     if (result != BitmapSuccess) {
  201.         if (interp != NULL) {
  202.         Tcl_AppendResult(interp, "error reading bitmap file \"", string,
  203.             "\"", (char *) NULL);
  204.         }
  205.         Tcl_DStringFree(&buffer);
  206.         goto error;
  207.     }
  208.     Tcl_DStringFree(&buffer);
  209.     } else {
  210.     predefHashPtr = Tcl_FindHashEntry(&tkPredefBitmapTable, string);
  211.     if (predefHashPtr == NULL) {
  212.         /*
  213.          * The following platform specific call allows the user to
  214.          * define bitmaps that may only exist during run time.  If
  215.          * it returns None nothing was found and we return the error.
  216.          */
  217.         bitmap = TkpGetNativeAppBitmap(Tk_Display(tkwin), string,
  218.             &width, &height);
  219.         
  220.         if (bitmap == None) {
  221.         if (interp != NULL) {
  222.             Tcl_AppendResult(interp, "bitmap \"", string,
  223.             "\" not defined", (char *) NULL);
  224.         }
  225.         goto error;
  226.         }
  227.     } else {
  228.         predefPtr = (TkPredefBitmap *) Tcl_GetHashValue(predefHashPtr);
  229.         width = predefPtr->width;
  230.         height = predefPtr->height;
  231.         if (predefPtr->native) {
  232.         bitmap = TkpCreateNativeBitmap(Tk_Display(tkwin),
  233.             predefPtr->source);
  234.         if (bitmap == None) {
  235.             panic("native bitmap creation failed");
  236.         }
  237.         } else {
  238.         bitmap = XCreateBitmapFromData(Tk_Display(tkwin),
  239.             RootWindowOfScreen(nameKey.screen), predefPtr->source,
  240.             (unsigned) width, (unsigned) height);
  241.         }
  242.     }
  243.     }
  244.  
  245.     /*
  246.      * Add information about this bitmap to our database.
  247.      */
  248.  
  249.     bitmapPtr = (TkBitmap *) ckalloc(sizeof(TkBitmap));
  250.     bitmapPtr->bitmap = bitmap;
  251.     bitmapPtr->width = width;
  252.     bitmapPtr->height = height;
  253.     bitmapPtr->display = Tk_Display(tkwin);
  254.     bitmapPtr->refCount = 1;
  255.     bitmapPtr->hashPtr = nameHashPtr;
  256.     idKey.display = bitmapPtr->display;
  257.     idKey.pixmap = bitmap;
  258.     idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey,
  259.         &new);
  260.     if (!new) {
  261.     panic("bitmap already registered in Tk_GetBitmap");
  262.     }
  263.     Tcl_SetHashValue(nameHashPtr, bitmapPtr);
  264.     Tcl_SetHashValue(idHashPtr, bitmapPtr);
  265.     return bitmapPtr->bitmap;
  266.  
  267.     error:
  268.     Tcl_DeleteHashEntry(nameHashPtr);
  269.     return None;
  270. }
  271.  
  272. /*
  273.  *----------------------------------------------------------------------
  274.  *
  275.  * Tk_DefineBitmap --
  276.  *
  277.  *    This procedure associates a textual name with a binary bitmap
  278.  *    description, so that the name may be used to refer to the
  279.  *    bitmap in future calls to Tk_GetBitmap.
  280.  *
  281.  * Results:
  282.  *    A standard Tcl result.  If an error occurs then TCL_ERROR is
  283.  *    returned and a message is left in interp->result.
  284.  *
  285.  * Side effects:
  286.  *    "Name" is entered into the bitmap table and may be used from
  287.  *    here on to refer to the given bitmap.
  288.  *
  289.  *----------------------------------------------------------------------
  290.  */
  291.  
  292. int
  293. Tk_DefineBitmap(interp, name, source, width, height)
  294.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  295.     Tk_Uid name;        /* Name to use for bitmap.  Must not already
  296.                  * be defined as a bitmap. */
  297.     char *source;        /* Address of bits for bitmap. */
  298.     int width;            /* Width of bitmap. */
  299.     int height;            /* Height of bitmap. */
  300. {
  301.     int new;
  302.     Tcl_HashEntry *predefHashPtr;
  303.     TkPredefBitmap *predefPtr;
  304.  
  305.     if (!initialized) {
  306.     BitmapInit();
  307.     }
  308.  
  309.     predefHashPtr = Tcl_CreateHashEntry(&tkPredefBitmapTable, name, &new);
  310.     if (!new) {
  311.         Tcl_AppendResult(interp, "bitmap \"", name,
  312.         "\" is already defined", (char *) NULL);
  313.     return TCL_ERROR;
  314.     }
  315.     predefPtr = (TkPredefBitmap *) ckalloc(sizeof(TkPredefBitmap));
  316.     predefPtr->source = source;
  317.     predefPtr->width = width;
  318.     predefPtr->height = height;
  319.     predefPtr->native = 0;
  320.     Tcl_SetHashValue(predefHashPtr, predefPtr);
  321.     return TCL_OK;
  322. }
  323.  
  324. /*
  325.  *--------------------------------------------------------------
  326.  *
  327.  * Tk_NameOfBitmap --
  328.  *
  329.  *    Given a bitmap, return a textual string identifying the
  330.  *    bitmap.
  331.  *
  332.  * Results:
  333.  *    The return value is the string name associated with bitmap.
  334.  *
  335.  * Side effects:
  336.  *    None.
  337.  *
  338.  *--------------------------------------------------------------
  339.  */
  340.  
  341. Tk_Uid
  342. Tk_NameOfBitmap(display, bitmap)
  343.     Display *display;            /* Display for which bitmap was
  344.                      * allocated. */
  345.     Pixmap bitmap;            /* Bitmap whose name is wanted. */
  346. {
  347.     IdKey idKey;
  348.     Tcl_HashEntry *idHashPtr;
  349.     TkBitmap *bitmapPtr;
  350.  
  351.     if (!initialized) {
  352.     unknown:
  353.     panic("Tk_NameOfBitmap received unknown bitmap argument");
  354.     }
  355.  
  356.     idKey.display = display;
  357.     idKey.pixmap = bitmap;
  358.     idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
  359.     if (idHashPtr == NULL) {
  360.     goto unknown;
  361.     }
  362.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
  363.     return ((NameKey *) bitmapPtr->hashPtr->key.words)->name;
  364. }
  365.  
  366. /*
  367.  *--------------------------------------------------------------
  368.  *
  369.  * Tk_SizeOfBitmap --
  370.  *
  371.  *    Given a bitmap managed by this module, returns the width
  372.  *    and height of the bitmap.
  373.  *
  374.  * Results:
  375.  *    The words at *widthPtr and *heightPtr are filled in with
  376.  *    the dimenstions of bitmap.
  377.  *
  378.  * Side effects:
  379.  *    If bitmap isn't managed by this module then the procedure
  380.  *    panics..
  381.  *
  382.  *--------------------------------------------------------------
  383.  */
  384.  
  385. void
  386. Tk_SizeOfBitmap(display, bitmap, widthPtr, heightPtr)
  387.     Display *display;            /* Display for which bitmap was
  388.                      * allocated. */
  389.     Pixmap bitmap;            /* Bitmap whose size is wanted. */
  390.     int *widthPtr;            /* Store bitmap width here. */
  391.     int *heightPtr;            /* Store bitmap height here. */
  392. {
  393.     IdKey idKey;
  394.     Tcl_HashEntry *idHashPtr;
  395.     TkBitmap *bitmapPtr;
  396.  
  397.     if (!initialized) {
  398.     unknownBitmap:
  399.     panic("Tk_SizeOfBitmap received unknown bitmap argument");
  400.     }
  401.  
  402.     idKey.display = display;
  403.     idKey.pixmap = bitmap;
  404.     idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
  405.     if (idHashPtr == NULL) {
  406.     goto unknownBitmap;
  407.     }
  408.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
  409.     *widthPtr = bitmapPtr->width;
  410.     *heightPtr = bitmapPtr->height;
  411. }
  412.  
  413. /*
  414.  *----------------------------------------------------------------------
  415.  *
  416.  * Tk_FreeBitmap --
  417.  *
  418.  *    This procedure is called to release a bitmap allocated by
  419.  *    Tk_GetBitmap or TkGetBitmapFromData.
  420.  *
  421.  * Results:
  422.  *    None.
  423.  *
  424.  * Side effects:
  425.  *    The reference count associated with bitmap is decremented, and
  426.  *    it is officially deallocated if no-one is using it anymore.
  427.  *
  428.  *----------------------------------------------------------------------
  429.  */
  430.  
  431. void
  432. Tk_FreeBitmap(display, bitmap)
  433.     Display *display;            /* Display for which bitmap was
  434.                      * allocated. */
  435.     Pixmap bitmap;            /* Bitmap to be released. */
  436. {
  437.     Tcl_HashEntry *idHashPtr;
  438.     register TkBitmap *bitmapPtr;
  439.     IdKey idKey;
  440.  
  441.     if (!initialized) {
  442.     panic("Tk_FreeBitmap called before Tk_GetBitmap");
  443.     }
  444.  
  445.     idKey.display = display;
  446.     idKey.pixmap = bitmap;
  447.     idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
  448.     if (idHashPtr == NULL) {
  449.     panic("Tk_FreeBitmap received unknown bitmap argument");
  450.     }
  451.     bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
  452.     bitmapPtr->refCount--;
  453.     if (bitmapPtr->refCount == 0) {
  454.     Tk_FreePixmap(bitmapPtr->display, bitmapPtr->bitmap);
  455.     Tcl_DeleteHashEntry(idHashPtr);
  456.     Tcl_DeleteHashEntry(bitmapPtr->hashPtr);
  457.     ckfree((char *) bitmapPtr);
  458.     }
  459. }
  460.  
  461. /*
  462.  *----------------------------------------------------------------------
  463.  *
  464.  * Tk_GetBitmapFromData --
  465.  *
  466.  *    Given a description of the bits for a bitmap, make a bitmap that
  467.  *    has the given properties. *** NOTE:  this procedure is obsolete
  468.  *    and really shouldn't be used anymore. ***
  469.  *
  470.  * Results:
  471.  *    The return value is the X identifer for the desired bitmap
  472.  *    (a one-plane Pixmap), unless it couldn't be created properly.
  473.  *    In this case, None is returned and an error message is left in
  474.  *    interp->result.  The caller should never modify the bitmap that
  475.  *    is returned, and should eventually call Tk_FreeBitmap when the
  476.  *    bitmap is no longer needed.
  477.  *
  478.  * Side effects:
  479.  *    The bitmap is added to an internal database with a reference count.
  480.  *    For each call to this procedure, there should eventually be a call
  481.  *    to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
  482.  *    aren't needed anymore.
  483.  *
  484.  *----------------------------------------------------------------------
  485.  */
  486.  
  487.     /* ARGSUSED */
  488. Pixmap
  489. Tk_GetBitmapFromData(interp, tkwin, source, width, height)
  490.     Tcl_Interp *interp;        /* Interpreter to use for error reporting. */
  491.     Tk_Window tkwin;        /* Window in which bitmap will be used. */
  492.     char *source;        /* Bitmap data for bitmap shape. */
  493.     int width, height;        /* Dimensions of bitmap. */
  494. {
  495.     DataKey nameKey;
  496.     Tcl_HashEntry *dataHashPtr;
  497.     Tk_Uid name;
  498.     int new;
  499.     char string[20];
  500.     static int autoNumber = 0;
  501.  
  502.     if (!initialized) {
  503.     BitmapInit();
  504.     }
  505.  
  506.     nameKey.source = source;
  507.     nameKey.width = width;
  508.     nameKey.height = height;
  509.     dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &nameKey, &new);
  510.     if (!new) {
  511.     name = (Tk_Uid) Tcl_GetHashValue(dataHashPtr);
  512.     } else {
  513.     autoNumber++;
  514.     sprintf(string, "_tk%d", autoNumber);
  515.     name = Tk_GetUid(string);
  516.     Tcl_SetHashValue(dataHashPtr, name);
  517.     if (Tk_DefineBitmap(interp, name, source, width, height) != TCL_OK) {
  518.         Tcl_DeleteHashEntry(dataHashPtr);
  519.         return TCL_ERROR;
  520.     }
  521.     }
  522.     return Tk_GetBitmap(interp, tkwin, name);
  523. }
  524.  
  525. /*
  526.  *----------------------------------------------------------------------
  527.  *
  528.  * BitmapInit --
  529.  *
  530.  *    Initialize the structures used for bitmap management.
  531.  *
  532.  * Results:
  533.  *    None.
  534.  *
  535.  * Side effects:
  536.  *    Read the code.
  537.  *
  538.  *----------------------------------------------------------------------
  539.  */
  540.  
  541. static void
  542. BitmapInit()
  543. {
  544.     Tcl_Interp *dummy;
  545.  
  546.     dummy = Tcl_CreateInterp();
  547.     initialized = 1;
  548.     Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
  549.     Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int));
  550.     Tcl_InitHashTable(&tkPredefBitmapTable, TCL_ONE_WORD_KEYS);
  551.  
  552.     /*
  553.      * The call below is tricky:  can't use sizeof(IdKey) because it
  554.      * gets padded with extra unpredictable bytes on some 64-bit
  555.      * machines.
  556.      */
  557.  
  558.     Tcl_InitHashTable(&idTable, (sizeof(Display *) + sizeof(Pixmap))
  559.         /sizeof(int));
  560.  
  561.     Tk_DefineBitmap(dummy, Tk_GetUid("error"), (char *) error_bits,
  562.         error_width, error_height);
  563.     Tk_DefineBitmap(dummy, Tk_GetUid("gray75"), (char *) gray75_bits,
  564.         gray75_width, gray75_height);
  565.     Tk_DefineBitmap(dummy, Tk_GetUid("gray50"), (char *) gray50_bits,
  566.         gray50_width, gray50_height);
  567.     Tk_DefineBitmap(dummy, Tk_GetUid("gray25"), (char *) gray25_bits,
  568.         gray25_width, gray25_height);
  569.     Tk_DefineBitmap(dummy, Tk_GetUid("gray12"), (char *) gray12_bits,
  570.         gray12_width, gray12_height);
  571.     Tk_DefineBitmap(dummy, Tk_GetUid("hourglass"), (char *) hourglass_bits,
  572.         hourglass_width, hourglass_height);
  573.     Tk_DefineBitmap(dummy, Tk_GetUid("info"), (char *) info_bits,
  574.         info_width, info_height);
  575.     Tk_DefineBitmap(dummy, Tk_GetUid("questhead"), (char *) questhead_bits,
  576.         questhead_width, questhead_height);
  577.     Tk_DefineBitmap(dummy, Tk_GetUid("question"), (char *) question_bits,
  578.         question_width, question_height);
  579.     Tk_DefineBitmap(dummy, Tk_GetUid("warning"), (char *) warning_bits,
  580.         warning_width, warning_height);
  581.  
  582.     TkpDefineNativeBitmaps();
  583.  
  584.     Tcl_DeleteInterp(dummy);
  585. }
  586.